const path = require('path')
const globby = require('globby')
const log = require('./log')
const OSS = require('./upload/oss')
const S3 = require('./upload/s3')
const packageJson = require('./package.json')

class WebpackPluginCdns {
  constructor(options) {
    this.uploadNum = 0 // 需上传数
    this.uploadedNum = 0 // 上传数
    this.options = options
  }
  apply(compiler) {
    if (compiler) {
      if (compiler.hooks) {
        // 推荐写法
        compiler.hooks.done.tapAsync('webpack-plugin-cdns', (stats) => {
          this.handle(compiler)
        })
      } else {
        // 兼容webpack3写法
        compiler.plugin('done', (stats) => {
          this.handle(compiler)
        })
      }
    } else {
      log.red(`[${packageJson.name}] compiler not found`)
    }
  }
  /**
   * 处理
   * @param {Object} compiler
   */
  handle(compiler) {
    // 检验参数配置必填项
    if (!this.checkOptions()) {
      return
    }
    // 上传目录处理，如果开始是/则删除斜杠
    this.options.dist.slice(0, 1)
    if (this.options.dist.slice(0, 1) === '/') {
      this.options.dist = this.options.dist.slice(1, this.options.dist.length - 1)
    }
    // 输出文件位置
    const outputPath = path.resolve(compiler.options.output.path)
    // 获取需要上传的资源文件
    globby(this.options.from).then((files) => {
      this.uploadNum = files.length
      log.blue(`[${packageJson.name}] Upload begin ...`)
      log.blue(`[${packageJson.name}] Number of uploaded files ${this.uploadNum}`)
      // 遍历编译资源文件
      for (const filename of files) {
        const uploadPath = path.normalize(this.options.dist + path.resolve(filename).split(outputPath)[1]).replace(/\\/g, '/')
        const localPath = path.normalize(path.resolve(filename))
        this.upload(uploadPath, localPath)
      }
    }).catch((err) => {
      console.error(err)
    })
  }
  /**
   * 获取CDN仓库目标
   */
  getType() {
    if (this.options.oss) {
      return 'oss'
    }
    if (this.options.s3) {
      return 's3'
    }
    return null
  }
  /**
   * 检验参数配置必填项
   */
  checkOptions() {
    // 通用配置检验
    if (!this.options.from) {
      log.red(`[${packageJson.name}] from not found in options`)
      return false
    }
    if (!this.options.dist) {
      log.red(`[${packageJson.name}] dist not found in options`)
      return false
    }
    // 不同CDN仓库的配置检验
    switch (this.getType()) {
    case 'oss':
      return OSS.check(this.options.oss)
    case 's3':
      return S3.check(this.options.s3)
    default:
      log.red(`[${packageJson.name}] CDN not configured (oss or s3)`)
      break
    }
  }
  /**
   * 上传文件
   * @param {String} uploadPath 上传路径
   * @param {String} localPath 本地文件路径
   */
  async upload(uploadPath, localPath) {
    // 上传
    let result = null
    switch (this.getType()) {
    case 'oss':
      result = await OSS.put(uploadPath, localPath, this.options.oss)
      break
    case 's3':
      result = await S3.put(uploadPath, localPath, this.options.s3)
      break
    default:
      return
    }
    // 处理上传结果
    if (result) {
      console.error(result)
    } else {
      // 成功 上传数+1, 上传数与需上传数相同时调用完成回调
      this.uploadedNum++
      if (this.uploadedNum === this.uploadNum) {
        log.blue(`[${packageJson.name}] File Total ${this.uploadedNum}`)
        log.blue(`[${packageJson.name}] Upload End ...`)
      }
    }
  }
}

module.exports = WebpackPluginCdns